home *** CD-ROM | disk | FTP | other *** search
/ Giga Games 1 / Giga Games.iso / net / usenet / volume5 / pi_perl < prev    next >
Encoding:
Internet Message Format  |  1988-08-30  |  9.9 KB

  1. Path: uunet!tektronix!tekgen!tekred!games
  2. From: games@tekred.TEK.COM
  3. Newsgroups: comp.sources.games
  4. Subject: v05i058:  pi-perl - compute the value of pi using perl (and C)
  5. Message-ID: <2988@tekred.TEK.COM>
  6. Date: 31 Aug 88 17:24:10 GMT
  7. Sender: billr@tekred.TEK.COM
  8. Lines: 418
  9. Approved: billr@saab.CNA.TEK.COM
  10.  
  11. Submitted by: uunet.uu.net!unido!nixpbe!kebsch
  12. Comp.sources.games: Volume 5, Issue 58
  13. Archive-name: pi-perl
  14.  
  15.  
  16.     [Is this a game or not? I'm not sure. In any event, it was sent
  17.      to me, so here it is.  -br]
  18.  
  19. [[The following two programs are for your entertainment. pi.pl is a perl script
  20. an pi.c is the equivalent written in C. Now you may compute pi (3,14....)
  21. about thousands of digits. Yes, the programs are just for fun, especially
  22. the pi.pl (Perl version)! :-)]]
  23.  
  24. #! /bin/sh
  25. # This is a shell archive, meaning:
  26. # 1. Remove everything above the #! /bin/sh line.
  27. # 2. Save the resulting text in a file.
  28. # 3. Execute the file with /bin/sh (not csh) to create:
  29. #    pi.pl
  30. #    pi.c
  31. # This archive created: Sat Aug  6 12:33:15 1988
  32. export PATH; PATH=/bin:/usr/bin:$PATH
  33. if test -f 'pi.pl'
  34. then
  35.     echo shar: "will not over-write existing file 'pi.pl'"
  36. else
  37. sed 's/^X//' << \SHAR_EOF > 'pi.pl'
  38. Xeval "exec nice -19 perl $0 $*"
  39. X    if $running_under_some_shell;
  40. X# ---------------------------------------------------------------------------
  41. X# pi.perl  computes pi (3.14...) about 5120 Digits
  42. X#
  43. X# W. Kebsch, July-1988  {uunet!mcvax}!unido!nixpbe!kebsch
  44. X
  45. X$my_name = `basename $0`; chop($my_name);
  46. X$version = $my_name . "-1.2";
  47. X
  48. X# some working parameter
  49. X
  50. X$smax =  5120;          # max digits
  51. X$lmax =     4;          # digits per one array element
  52. X$hmax = 10000;          # one array element contains: 0..9999
  53. X$smin = $lmax;          # min digits
  54. X$mag  =     7;          # magic number
  55. X
  56. X# subroutines
  57. X
  58. Xsub mul_tm              # multiply the tm array with a long value
  59. X{
  60. X    $cb = pop(@_);      # elements(array)
  61. X    $x  = pop(@_);      # value
  62. X
  63. X    $c = 0;
  64. X    for($i = 1; $i <= $cb; $i++)
  65. X    {
  66. X    $z      = $tm[$i] * $x + $c;
  67. X    $c      = int($z / $hmax);
  68. X    $tm[$i] = $z - $c * $hmax;
  69. X    }
  70. X}
  71. X
  72. Xsub mul_pm              # multiply the pm array with a long value
  73. X{
  74. X    $cb = pop(@_);      # elements(array)
  75. X    $x  = pop(@_);      # value
  76. X
  77. X    $c = 0;
  78. X    for($i = 1; $i <= $cb; $i++)
  79. X    {
  80. X    $z      = $pm[$i] * $x + $c;
  81. X    $c      = int($z / $hmax);
  82. X    $pm[$i] = $z - $c * $hmax;
  83. X    }
  84. X}
  85. X
  86. Xsub divide              # divide the tm array by a long value
  87. X{
  88. X    $cb = pop(@_);      # elements(array)
  89. X    $x  = pop(@_);      # value
  90. X
  91. X    $c = 0;
  92. X    for($i = $cb; $i >= 1; $i--)
  93. X    {
  94. X    $z      = $tm[$i] + $c;
  95. X    $q      = int($z / $x);
  96. X    $tm[$i] = $q;
  97. X    $c      = ($z - $q * $x) * $hmax;
  98. X    }
  99. X}
  100. X
  101. Xsub add                 # add tm array to pm array
  102. X{
  103. X    $cb = pop(@_);      # elements(array)
  104. X
  105. X    $c = 0;
  106. X    for($i = 1; $i <= $cb; $i++)
  107. X    {
  108. X    $z = $pm[$i] + $tm[$i] + $c;
  109. X    if($z >= $hmax)
  110. X    {
  111. X        $pm[$i] = $z - $hmax;
  112. X        $c      = 1;
  113. X    }
  114. X    else
  115. X    {
  116. X        $pm[$i] = $z;
  117. X        $c      = 0;
  118. X    }
  119. X    }
  120. X}
  121. X
  122. X$m0 = 0; $m1 = 0; $m2 = 0;
  123. X
  124. Xsub check_xb            # reduce current no. of elements (speed up!)
  125. X{
  126. X    $cb = pop(@_);      # current no. of elements
  127. X
  128. X    if(($pm[$cb] == $m0) && ($pm[$cb - 1] == $m1) && ($pm[$cb - 2] == $m2))
  129. X    {
  130. X    $cb--;
  131. X    }
  132. X    $m0 = $pm[$cb];
  133. X    $m1 = $pm[$cb - 1];
  134. X    $m2 = $pm[$cb - 2];
  135. X    $cb;
  136. X}
  137. X
  138. Xsub display             # show the result
  139. X{
  140. X    $cb = pop(@_);      # elements(array);
  141. X
  142. X    printf("\n%3d.", $pm[$cb]);
  143. X    $j = $mag - $lmax;
  144. X    for($i = $cb - 1; $i >= $j; $i--)
  145. X    {
  146. X    printf(" %04d", $pm[$i]);
  147. X    }
  148. X    print "\n";
  149. X}
  150. X
  151. Xsub the_job             # let's do the job
  152. X{
  153. X    $s = pop(@_);       # no. of digits
  154. X
  155. X    $s  = int(($s + $lmax - 1) / $lmax) * $lmax;
  156. X    $b  = int($s / $lmax) + $mag - $lmax;
  157. X    $xb = $b;
  158. X    $t  = int($s * 5 / 3);
  159. X
  160. X    for($i = 1; $i <= $b; $i++)         # init arrays
  161. X    {
  162. X    $pm[$i] = 0;
  163. X    $tm[$i] = 0;
  164. X    }
  165. X    $pm[$b - 1] = $hmax / 2;
  166. X    $tm[$b - 1] = $hmax / 2;
  167. X
  168. X    printf("digits:%5d, terms:%5d, elements:%5d\n", $s, $t, $b);
  169. X    for($n = 1; $n <= $t; $n++)
  170. X    {
  171. X    printf("\r\t\t\t  term:%5d", $n);
  172. X    if($n < 200)
  173. X    {
  174. X        do mul_tm((4 * ($n * $n - $n) + 1), $xb);
  175. X    }
  176. X    else
  177. X    {
  178. X        do mul_tm((2 * $n - 1), $xb);
  179. X        do mul_tm((2 * $n - 1), $xb);
  180. X    }
  181. X    if($n < 100)
  182. X    {
  183. X        do divide(($n * (16 * $n + 8)), $xb);
  184. X    }
  185. X    else
  186. X    {
  187. X        do divide((8 * $n), $xb);
  188. X        do divide((2 * $n + 1), $xb);
  189. X    }
  190. X    do add($xb);
  191. X    if($xb > $mag)
  192. X    {
  193. X        $xb = do check_xb($xb);
  194. X    }
  195. X    }
  196. X    do mul_pm(6, $b);
  197. X    do display($b);
  198. X    ($user,$sys,$cuser,$csys) = times;
  199. X    printf("\n[u=%g  s=%g  cu=%g  cs=%g]\n",$user, $sys, $cuser, $csys);
  200. X}
  201. X
  202. X# main block ----------------------------------------------------------------
  203. X
  204. X$no_of_args = $#ARGV + 1;
  205. Xprint("$version, ");
  206. Xdie("usage: $my_name <no. of digits>") unless($no_of_args == 1);
  207. X$digits = int($ARGV[0]);
  208. Xdie("no. of digits out of range [$smin\..$smax]")
  209. X                unless(($digits >= $smin) && ($digits <= $smax));
  210. Xdo the_job($digits);
  211. Xexit 0;
  212. X
  213. X# That's all ----------------------------------------------------------------
  214. SHAR_EOF
  215. if test 3802 -ne "`wc -c < 'pi.pl'`"
  216. then
  217.     echo shar: "error transmitting 'pi.pl'" '(should have been 3802 characters)'
  218. fi
  219. fi
  220. if test -f 'pi.c'
  221. then
  222.     echo shar: "will not over-write existing file 'pi.c'"
  223. else
  224. sed 's/^X//' << \SHAR_EOF > 'pi.c'
  225. X/*   ------------------------------------------------------------------
  226. X *   Function: Compute a long PI-constant     (4..15,000 see    "smax")
  227. X *
  228. X *   Made by Waldemar Kebsch, Salzkotten, Germany - December 1985
  229. X *                              UUCP: {uunet,mcvax}!unido!nixpbe!kebsch
  230. X *
  231. X *   Usage: pi [number]          (number of digits    on the right hand)
  232. X */
  233. X
  234. X#include <stdio.h>;
  235. X
  236. X#define VERSION  ("  V-1.10  ")
  237. X
  238. X#define     hmax      10000l        /* one element contains: 0..9999 */
  239. X#define     lmax           4        /* max digits of an    element         */
  240. X#define     smin        lmax        /* min digits on the right hand  */
  241. X#define     smax        15000        /* max digits ..             */
  242. X#define     ml   (1+smax/lmax+7-lmax)  /* max. necessary matrix length  */
  243. X
  244. X
  245. Xmain(argc, argv)  /* Parameter:    Number of digits */
  246. Xint argc;
  247. Xchar **argv;
  248. X{          /* 1.    Check Parameter    */
  249. X    int    s;
  250. X
  251. X    if(argc < 2)
  252. X    {
  253. X    printf("Missing argument.\n");
  254. X    exit(1);
  255. X    }
  256. X    if(argc > 2)
  257. X    {
  258. X    printf("Too many arguments.\n");
  259. X    exit(1);
  260. X    }
  261. X    if(sscanf(*++argv, "%d", &s) != 1)
  262. X    {
  263. X    printf("Syntax error.\n");
  264. X    exit(1);
  265. X    }
  266. X    if(s < smin    || s > smax)
  267. X    {
  268. X    printf("Sorry, out of range.\n");
  269. X    exit(1);
  270. X    }
  271. X
  272. X    doit(s);      /* 2.    Let's do it */
  273. X}
  274. X
  275. X
  276. Xdoit(s)       /* Work */
  277. Xint s;
  278. X{
  279. X    char *malloc();
  280. X    long  *pm;           /* primarily matrix */
  281. X    long  *tm;           /* secondary matrix */
  282. X    int      b, xb;       /* number of necessary blocks (elem.) in    the matrix */
  283. X    long  n, t;           /* n=current term, t=max. terms */
  284. X
  285. X    s =    ((s + lmax - 1)    / lmax)    * lmax;        /* digits */
  286. X    b =    xb = s / lmax +    7 - lmax;        /* blocks */
  287. X    t =    s + 2l * s / 3l;            /* terms  */
  288. X    pm = (long*)malloc(b * sizeof(long));   /* array pm   */
  289. X    tm = (long*)malloc(b * sizeof(long));   /* array tm   */
  290. X
  291. X    initial(pm,    tm, b);
  292. X
  293. X    printf("\n");
  294. X    printf VERSION;
  295. X    printf("digits: %5d,  terms: %5d, ", s, t);
  296. X    printf("blocks: %5d\n", b);
  297. X    nice(19);
  298. X
  299. X    for(n = 1l;    n <= t;    n++)   /* time eating loop */
  300. X    {
  301. X    printf("\rterm: %5d ", n); fflush(stdout);
  302. X    if(n < 232l)
  303. X        multiply(tm, (4l * (n * n -    n) + 1l), xb);
  304. X    else
  305. X    {
  306. X        multiply(tm, (2l * n - 1l),    xb );
  307. X        multiply(tm, (2l * n - 1l),    xb );
  308. X    }
  309. X    if(n < 115l)
  310. X        divide(tm, (n * (16l * n + 8l)), xb);
  311. X    else
  312. X    {
  313. X        divide(tm, (8l * n), xb );
  314. X        divide(tm, (2l * n + 1l), xb );
  315. X    }
  316. X
  317. X    add(pm,    tm, xb);
  318. X    xb = checkxb(pm, xb);
  319. X    }
  320. X
  321. X    multiply(pm, 6l, b);
  322. X    display(pm,    b);
  323. X}
  324. X
  325. Xinitial(cm1, cm2, cb)       /* cm1 = cm2    = 0.5 */
  326. Xregister long *cm1, *cm2;  /* current matrix */
  327. Xint cb;
  328. X{
  329. X    long *cmm;
  330. X
  331. X    for(cmm = cm1 + cb;    cm1 < cmm; )
  332. X    *++cm1 = *++cm2    = 0;
  333. X
  334. X    *--cm1 = *--cm2 = hmax / 2l;
  335. X}
  336. X
  337. Xcheckxb(cm, cb)       /* Reduce current block number (speed up) */
  338. Xregister long *cm;
  339. Xint cb;
  340. X{
  341. X    static long    mm = 0,    mn = 0,    nn = 0;
  342. X    register long *cmm;
  343. X
  344. X    cmm    = cm;
  345. X    cm += cb;
  346. X    if(*cm == mm && *--cm == mn    && *--cm == nn)
  347. X    cb--;
  348. X
  349. X    cmm    += cb;
  350. X    mm = *cmm;
  351. X    mn = *--cmm;
  352. X    nn = *--cmm;
  353. X    return(cb);
  354. X}
  355. X
  356. Xmultiply(cm, x,    cb)  /*    cm *= x    */
  357. Xregister long *cm;   /*    current    matrix     */
  358. Xlong x;        /* multiply    with ..    */
  359. Xint cb;        /* current blocks    */
  360. X{
  361. X    long *cmm;
  362. X    long c, z;      /*      carry    */
  363. X
  364. X    for(c = 0, cmm = cm    + cb; cm < cmm;    )
  365. X    {
  366. X    z = *++cm * x +    c;
  367. X    c = z /    hmax;
  368. X    *cm = z    - c * hmax;      /* the same as "*cm = z % hmax;" */
  369. X    }                  /* but faster! */
  370. X}
  371. X
  372. Xdivide(cm, x, cb)  /* cm /= x */
  373. Xregister long *cm;   /*    current    matrix */
  374. Xlong x;        /* divide by ..   */
  375. Xint cb;        /* current blocks */
  376. X{
  377. X    long *cmm;
  378. X    long c, z, q;      /* c=carry, z, q=temporary variable */
  379. X
  380. X    for(c = 0, cmm = cm, cm += cb; cm >    cmm; )
  381. X    {
  382. X    z = *cm    + c;
  383. X    *cm-- =    q = z /    x;
  384. X    c = (z - q * x)    * hmax;      /* the same as  "c = (z % x) * hmax;"    */
  385. X    }                  /* but faster! */
  386. X}
  387. X
  388. Xadd(cm1, cm2, cb)    /* cm1 += cm2 */
  389. Xregister long *cm1, *cm2;    /*    current    matrix */
  390. Xint cb;            /* current blocks */
  391. X{
  392. X    long *cmm;
  393. X    long c;  /*    carry */
  394. X
  395. X    for(c = 0, cmm = cm1 + cb; cm1 < cmm; )
  396. X    {
  397. X    if((*++cm1 += (*++cm2 +    c)) >= hmax)
  398. X    {
  399. X        *cm1 -= hmax;
  400. X        c =    1;
  401. X    }
  402. X    else
  403. X        c =    0;
  404. X    }
  405. X}
  406. X
  407. Xdisplay(cm, cb)
  408. Xregister long *cm;  /* current matrix */
  409. Xint cb;
  410. X{
  411. X    int    i;
  412. X
  413. X    printf("\n%1d. \n",    *(cm +=    cb));     /* one    digit on the left hand */
  414. X    for(i = cb-1; i >= (7-lmax); i--)
  415. X    printf(" %04d",    *--cm);          /* print all digits on the rigth hand */
  416. X
  417. X    printf("\n");
  418. X}
  419. X
  420. X/* That's all */
  421. SHAR_EOF
  422. if test 4336 -ne "`wc -c < 'pi.c'`"
  423. then
  424.     echo shar: "error transmitting 'pi.c'" '(should have been 4336 characters)'
  425. fi
  426. fi
  427. #    End of shell archive
  428. exit 0
  429.